package com.xfatm.util.csv;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CsvHandle {

    private String path;
    private char split;
    private Charset charset;
    private List<String> lines=new ArrayList<>();
    private Map<Integer,List<String>> lineMap=new HashMap<>();

    private CsvHandle(String path, char split, Charset charset){
        this.path=path;
        this.split=split;
        this.charset=charset;
        readCsv();
    }

    public String getLine(int index){
        StringBuffer line=new StringBuffer();
        List<String> lines=getHandleLine(index);
        for(String cell:lines){
            line.append(split).append(cell);
        }
        if(line.length()==0){
            return "";
        }
        return line.substring(1);
    }

    public String getString(int row,int col){
        return getHandleLine(row).get(col);
    }

    public int getInteger(int row,int col){
        return Integer.parseInt(getString(row,col));
    }

    public long getLong(int row,int col){
        return Long.parseLong(getString(row,col));
    }

    public int getRowSize(){
        return lines.size();
    }

    public int getColumnSize(){
        return lines.size()==0?0:getHandleLine(0).size();
    }

    private List<String> getHandleLine(int index){
        if(lineMap.get(index)!=null){
            return lineMap.get(index);
        }
        String line=lines.get(index);
        //是否第一次读取否个单元格内容
        boolean isCellStart=true;
        //引号出现次数
        int symbolNum=0;
        char[] lineChars=line.toCharArray();
        List<String> lineList=new ArrayList<>();
        StringBuffer cellData=new StringBuffer();
        for(char c:lineChars) {
            if(c=='"') {
                symbolNum++;
                if (!isCellStart) {
                    if (symbolNum % 2 == 1) {
                        cellData.append(c);
                    }
                }
                isCellStart = false;
            }else if(c==split) {
                if (symbolNum % 2 == 0) {
                    lineList.add(cellData.toString());
                    symbolNum = 0;
                    cellData = new StringBuffer();
                    isCellStart = true;
                } else {
                    cellData.append(c);
                    isCellStart = false;
                }
            }else {
                cellData.append(c);
                isCellStart = false;
            }
        }
        lineList.add(cellData.toString());
        return lineList;
    }


    private void readCsv(){
        try(BufferedReader reader=new BufferedReader(new InputStreamReader(new FileInputStream(new File(path)),charset.name()))){
            String line=null;
            boolean isFirstLine=true;
            while((line=reader.readLine())!=null){
                if(isFirstLine){
                    byte[] lineBytes=line.getBytes();
                    if(lineBytes[0]==(byte)0xef&&lineBytes[1]==(byte)0xbb&&lineBytes[2]==(byte)0xbf){
                        line=new String(lineBytes,3,lineBytes.length-3);
                    }
                    isFirstLine=false;
                }
                lines.add(line);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static CsvHandle loadCsv(String path, char split){
        return loadCsv(path,split,Charset.forName("UTF-8"));
    }

    public static CsvHandle loadCsv(String path, char split, Charset charset){
        return new CsvHandle(path,split,charset);

    }

    @Override
    public String toString() {
        StringBuffer content=new StringBuffer();
        lines.forEach(l->content.append("\n").append(l));
        return content.substring(1);
    }
}
